﻿using System.Collections.Generic;
using Keysight.Tap;

namespace OpenTap.Plugins.AcPsu
{
    /// <summary>
    ///     This enum is used to set voltage mode with Keysight AC6800-series.
    /// </summary>
    public enum EVoltageMode
    {
        [Scpi("AC")] Ac,
        [Scpi("DC")] Dc,   //NO need yet. Will be added when need occurs
        [Scpi("ACDC")] AcDc   //NO need yet. Will be added when need occurs
    }

    /// <summary>
    ///     This enum is used to set voltage range with Keysight AC6800-series and Kikusui PCR2000-series PSU:s.
    /// </summary>
    public enum EVoltageRange
    {
        [Display("135V")] RangeLoV = 135,
        [Display("270V")] RangeHiV = 270,
        [Display("Auto")] RangeAuto
    }

    /// <summary>
    ///     This enum is used to set/inform ON- or OFF-states with methods: SetOutputState(), SetCurrentProtectionState() and GetCurrentProtectionStatus().
    /// </summary>
    public enum EState
    {
        Off,
        On
    }

    /// <summary>
    ///     This enum is used to inform, if all previously executed SCPI commands have been completed or not (=Incomplete).
    /// </summary>
    public enum EOpcStatus
    {
        Incomplete = 0,
        Complete = 1
    }

    public enum ERemoteInhibitMode
    {
        [Scpi("LATC")] Latc,     // A TTL low at the RI input latches the output in the protection shutdown state, which
        // can only be cleared by OUTPut:PROTection:CLEar.
        [Scpi("LIVE")] Live,     // The output state follows the state of the RI input. A TTL low at the RI input turns the output off.
        //                                                     A TTL high turns the output on.
        [Scpi("OFF")] Off        // The instrument ignores the RI input.
    }

    public enum ERemoteInhibitLevel
    {
        [Scpi("LOW")] Low,   // Factory default is LOW, which requires a contact closure to open the output relay.
        [Scpi("HIGH")] High  // The level can be reversed by setting it to HIGH
    }

    public interface IAcPsu : IInstrument
    {
        /// <summary>
        ///     Resets any tripped protection from instrument.
        /// </summary>
        void ClearOutputProtection();

        /// <summary>
        ///     Gets the AC current limit which is set to instrument.
        /// </summary>
        /// <returns>The defined current limit in ampere. NaN if not set yet.</returns>
        double GetCurrentLimit();

        /// <summary>
        ///     Gets the DC current limit which is set to instrument.
        /// </summary>
        /// <returns>The defined current limit in ampere. NaN if not set yet.</returns>
        double GetCurrentLimitDc();

        /// <summary>
        ///     Asks the current protection status from instrument.
        /// </summary>
        /// <returns>The current protection status</returns>
        EState GetCurrentProtectionStatus();

        /// <summary>
        ///     Gets the frequency set to AC output.
        /// </summary>
        /// <returns>Set frequency in Hz. NaN if not set</returns>
        double GetFrequency();

        /// <summary>
        ///     Checks all protection status states from instrument.
        /// </summary>
        /// <returns>The overall protection status. 0 = No active protections.</returns>
        int GetProtectionStatusAll();

        /// <summary>
        ///     Gets the voltage AC level that is set to instrument.
        /// </summary>
        /// <returns>The defined voltage limit in volts [VAC]. NaN if not set</returns>
        double GetVoltageLevel();

        /// <summary>
        ///     Gets the output DC voltage setvalue from the instrument.
        /// </summary>
        /// <returns>Voltage set value [VDC]</returns>
        double GetVoltageLevelDc();

        /// <summary>
        ///     Gets the output DC voltage protection lower set value from the instrument.
        /// </summary>
        /// <returns>Voltage DC limit [VDC]</returns>
        double GetVoltageDcProtectionLimitLower();

        /// <summary>
        ///     Gets the output DC voltage protection upper set value from to the instrument.
        /// </summary>
        /// <returns>Voltage DC limit [VDC]</returns>
        double GetVoltageDcProtectionLimitUpper();

        /// <summary>
        ///     Gets the output DC voltage protection state from the instrument.
        /// </summary>
        /// <returns>Voltage DC protection state</returns>
        EState GetVoltageDcProtectionState();

        /// <summary>
        ///     Gets the output voltage mode from the instrument.
        /// </summary>
        /// <returns>Voltage mode</returns>
        EVoltageMode GetVoltageMode();

        /// <summary>
        ///     Gets the output voltage range setting from the instrument.
        /// </summary>
        /// <returns>Voltage range setting [VAC]</returns>
        double GetVoltageRange();

        /// <summary>
        ///     Gets the instrument identity string. (As returned by the SCPI command *IDN?).
        /// </summary>
        /// <returns></returns>
        string IdnString();

        /// <summary>
        ///     Starts a new measurement and then queries the AC current.
        /// </summary>
        /// <returns>Returns AC current (Arms)</returns>
        double MeasureCurrent();

        /// <summary>
        ///     Starts a new measurement and then queries the AC power
        /// </summary>
        /// <returns>Returns the AC power [W]</returns>
        double MeasureActualPowerW();

        /// <summary>
        ///     Starts a new measurement and then queries the AC power (the apparent power).
        /// </summary>
        /// <returns>Returns the AC power (the apparent power) [VA]</returns>
        // ReSharper disable once InconsistentNaming
        double MeasureApparentPowerVA();

        /// <summary>
        ///     Starts a new measurement and then queries the DC current.
        /// </summary>
        /// <returns>Returns DC current (A)</returns>
        double MeasureCurrentDc();

        /// <summary>
        ///     Starts a new measurement and then queries the peak current.
        /// </summary>
        /// <returns>Returns the peak current</returns>
        double MeasurePeakCurrent();

        /// <summary>
        ///     Starts a new measurement and then queries the AC power factor
        /// </summary>
        /// <returns>Returns the AC power factor</returns>
        double MeasurePowerFactor();

        /// <summary>
        ///      Starts a new measurement and then queries the AC power (the reactive power).
        /// </summary>
        /// <returns>Returns the AC power (the reactive power) [VAR]</returns>
        // ReSharper disable once InconsistentNaming
        double MeasureReactivePowerVAR();

        /// <summary>
        ///     Starts a new measurement and then queries the AC voltage.
        /// </summary>
        /// <returns>Returns the AC voltage [VAC]</returns>
        double MeasureVoltage();

        /// <summary>
        ///     Starts a new measurement and then queries the DC voltage.
        /// </summary>
        /// <returns>Returns the DC voltage [VDC]</returns>
        double MeasureVoltageDc();

        /// <summary>
        ///     Returns all the errors on the instrument error stack. Clears the list in
        ///     the same call.
        /// </summary>
        /// <param name="suppressLogMessages">if true the errors will not be logged</param>
        /// <param name="maxErrors">
        ///     The max number of errors to retrieve. Useful if instrument generates errors faster than they
        ///     can be read.
        /// </param>
        /// <returns></returns>
        List<ScpiInstrument.ScpiError> QueryErrors(bool suppressLogMessages = false, int maxErrors = 1000);

        /// <summary>
        ///     Querys ERRors and throws an exception, if wanted.
        /// </summary>
        /// <param name="ifErrRunException">
        ///     If true, run Exception with error. False can be used to clean error queue without exception.
        /// </param>
        /// <param name="infoMessToShow">
        ///     Info message to be shown with exception.
        /// </param>
        /// <returns></returns>
        void QueryErrWithExc(bool ifErrRunException = true, string infoMessToShow = "PutHereInfoMessToBeShownWithException");

        /// <summary>
        ///     Reset the instrument to its factory default condition (*RST).
        /// </summary>
        /// <returns></returns>
        void Reset();

        /// <summary>
        ///     Reads the result of power-on self-test. (SCPI command *TST?).
        /// </summary>
        /// <returns>Result of selftest: 0, if pass. Error code, if there are errors.</returns>
        int SelfTest();

        /// <summary>
        ///     Sets the maximum AC current limit to instrument.
        ///     Kikusui and Keysight runs different, when set value is out of current MIN/MAX limits.
        ///     This driver makes functionalty looking same with both of them. See overrides.
        /// </summary>
        /// <param name="currentAmps">Current limit in Amperes</param>
        void SetCurrent(double currentAmps);

        /// <summary>
        ///     Sets the maximum DC current limit to instrument.
        /// </summary>
        /// <param name="currentAmps">Current limit in Amperes</param>
        void SetCurrentDc(double currentAmps);

        /// <summary>
        ///     Sets the current protection state to instrument.
        /// </summary>
        /// <param name="state">State to be set</param>
        void SetCurrentProtectionState(EState state);

        /// <summary>
        ///     Sets the AC output frequency.
        /// </summary>
        /// <param name="freqHertz">Frequency to be set in hertz</param>
        void SetFrequency(double freqHertz);

        /// <summary>
        ///     Sets the output state to the instrument.
        /// </summary>
        /// <param name="state">The state to be set</param>
        void SetOutputState(EState state);

        /// <summary>
        ///     Sets the output voltage to the instrument.
        /// </summary>
        /// <param name="voltageV">Voltage to be set to PSU [VAC]</param>
        void SetVoltage(double voltageV);

        /// <summary>
        ///     Sets the output DC voltage to the instrument.
        /// </summary>
        /// <param name="voltageDc">Voltage [VDC]</param>
        void SetVoltageDc(double voltageDc);

        /// <summary>
        ///     Sets the output DC voltage protection limit to the instrument.
        /// </summary>
        /// <param name="voltageDcLimitLow">Voltage DC limit to be set to PSU [VDC]</param>
        void SetVoltageDcProtectionLimitLower(double voltageDcLimitLow);

        /// <summary>
        ///     Sets the output DC voltage protection limit to the instrument.
        /// </summary>
        /// <param name="voltageDcLimitUpp">Voltage DC limit to be set to PSU [VDC]</param>
        void SetVoltageDcProtectionLimitUpper(double voltageDcLimitUpp);

        /// <summary>
        ///     Sets the output DC voltage protection state ON/OFF.
        /// </summary>
        void SetVoltageDcProtectionState(EState onOff);

        /// <summary>
        ///     Sets the output voltage mode to the instrument.
        /// </summary>
        /// <param name="voltageMode">Voltage mode [AC/DC] to be set to PSU</param>
        void SetVoltageMode(EVoltageMode voltageMode);

        /// <summary>
        ///     Sets the output voltage range to the instrument.
        /// </summary>
        /// <param name="voltageRangeV">Voltage range [V] to be set to PSU</param>
        void SetVoltageRange(int voltageRangeV);
    }
}